home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / gfx / show / JPEGv42source.lha / GC / JPEG / jcmain.c < prev    next >
C/C++ Source or Header  |  1993-06-05  |  18KB  |  606 lines

  1. /*
  2.  * jcmain.c
  3.  *
  4.  * Copyright (C) 1991, 1992, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains a command-line user interface for the JPEG compressor.
  9.  * It should work on any system with Unix- or MS-DOS-style command lines.
  10.  *
  11.  * Two different command line styles are permitted, depending on the
  12.  * compile-time switch TWO_FILE_COMMANDLINE:
  13.  *    cjpeg [options]  inputfile outputfile
  14.  *    cjpeg [options]  [inputfile]
  15.  * In the second style, output is always to standard output, which you'd
  16.  * normally redirect to a file or pipe to some other program.  Input is
  17.  * either from a named file or from standard input (typically redirected).
  18.  * The second style is convenient on Unix but is unhelpful on systems that
  19.  * don't support pipes.  Also, you MUST use the first style if your system
  20.  * doesn't do binary I/O to stdin/stdout.
  21.  */
  22.  
  23. #define TWO_FILE_COMMANDLINE
  24. #define PROGRESS_REPORT
  25.  
  26. #include "jinclude.h"
  27. #ifdef INCLUDES_ARE_ANSI
  28. #include <stdlib.h>        /* to declare exit() */
  29. #endif
  30. #include <ctype.h>        /* to declare isupper(), tolower() */
  31. #ifdef NEED_SIGNAL_CATCHER
  32. #include <signal.h>        /* to declare signal() */
  33. #endif
  34. #ifdef USE_SETMODE
  35. #include <fcntl.h>        /* to declare setmode() */
  36. #endif
  37.  
  38. #ifdef THINK_C
  39. #include <console.h>        /* command-line reader for Macintosh */
  40. #endif
  41.  
  42. #ifdef DONT_USE_B_MODE        /* define mode parameters for fopen() */
  43. #define READ_BINARY    "r"
  44. #define WRITE_BINARY    "w"
  45. #else
  46. #define READ_BINARY    "rb"
  47. #define WRITE_BINARY    "wb"
  48. #endif
  49.  
  50. #ifndef EXIT_FAILURE        /* define exit() codes if not provided */
  51. #define EXIT_FAILURE  1
  52. #endif
  53. #ifndef EXIT_SUCCESS
  54. #ifdef VMS
  55. #define EXIT_SUCCESS  1        /* VMS is very nonstandard */
  56. #else
  57. #define EXIT_SUCCESS  0
  58. #endif
  59. #endif
  60.  
  61.  
  62. #include "jversion.h"        /* for version message */
  63.  
  64. /*
  65.  * This routine gets control after the input file header has been read.
  66.  * It must determine what output JPEG file format is to be written,
  67.  * and make any other compression parameter changes that are desirable.
  68.  */
  69.  
  70. METHODDEF void
  71. c_ui_method_selection (compress_info_ptr cinfo)
  72. {
  73.   /* If the input is gray scale, generate a monochrome JPEG file. */
  74.   if (cinfo->in_color_space == CS_GRAYSCALE)
  75.     j_monochrome_default(cinfo);
  76.   /* For now, always select JFIF output format. */
  77. #ifdef JFIF_SUPPORTED
  78.   jselwjfif(cinfo);
  79. #else
  80.   You shoulda defined JFIF_SUPPORTED.   /* deliberate syntax error */
  81. #endif
  82. }
  83.  
  84.  
  85. /*
  86.  * Signal catcher to ensure that temporary files are removed before aborting.
  87.  * NB: for Amiga Manx C this is actually a global routine named _abort();
  88.  * see -Dsignal_catcher=_abort in CFLAGS.  Talk about bogus...
  89.  */
  90.  
  91. #ifdef NEED_SIGNAL_CATCHER
  92.  
  93. static external_methods_ptr emethods; /* for access to free_all */
  94.  
  95. GLOBAL void
  96. signal_catcher (int signum)
  97. {
  98.   if (emethods != NULL) {
  99.     emethods->trace_level = 0;    /* turn off trace output */
  100.     (*emethods->free_all) ();    /* clean up memory allocation & temp files */
  101.   }
  102.   exit(EXIT_FAILURE);
  103. }
  104.  
  105. #endif
  106.  
  107.  
  108. /*
  109.  * Optional routine to display a percent-done figure on stderr.
  110.  * See jcdeflts.c for explanation of the information used.
  111.  */
  112.  
  113. #ifdef PROGRESS_REPORT
  114.  
  115. METHODDEF void
  116. progress_monitor (compress_info_ptr cinfo, long loopcounter, long looplimit)
  117. {
  118.   if (cinfo->total_passes > 1) {
  119.     fprintf(stderr, "\rPass %d/%d: %3d%% ",
  120.         cinfo->completed_passes+1, cinfo->total_passes,
  121.         (int) (loopcounter*100L/looplimit));
  122.   } else {
  123.     fprintf(stderr, "\r %3d%% ",
  124.         (int) (loopcounter*100L/looplimit));
  125.   }
  126.   fflush(stderr);
  127. }
  128.  
  129. #endif
  130.  
  131.  
  132. /*
  133.  * Argument-parsing code.
  134.  * The switch parser is designed to be useful with DOS-style command line
  135.  * syntax, ie, intermixed switches and file names, where only the switches
  136.  * to the left of a given file name affect processing of that file.
  137.  * The main program in this file doesn't actually use this capability...
  138.  */
  139.  
  140.  
  141. static char * progname;        /* program name for error messages */
  142.  
  143.  
  144. LOCAL void
  145. usage (void)
  146. /* complain about bad command line */
  147. {
  148.   fprintf(stderr, "usage: %s [switches] ", progname);
  149. #ifdef TWO_FILE_COMMANDLINE
  150.   fprintf(stderr, "inputfile outputfile\n");
  151. #else
  152.   fprintf(stderr, "[inputfile]\n");
  153. #endif
  154.  
  155.   fprintf(stderr, "Switches (names may be abbreviated):\n");
  156.   fprintf(stderr, "  -quality N     Compression quality (0..100; 5-95 is useful range)\n");
  157.   fprintf(stderr, "  -grayscale     Create monochrome JPEG file\n");
  158. #ifdef ENTROPY_OPT_SUPPORTED
  159.   fprintf(stderr, "  -optimize      Optimize Huffman table (smaller file, but slow compression)\n");
  160. #endif
  161.   fprintf(stderr, "Switches for advanced users:\n");
  162.   fprintf(stderr, "  -restart N     Set restart interval in rows, or in blocks with B\n");
  163. #ifdef INPUT_SMOOTHING_SUPPORTED
  164.   fprintf(stderr, "  -smooth N      Smooth dithered input (N=1..100 is strength)\n");
  165. #endif
  166.   fprintf(stderr, "  -maxmemory N   Maximum memory to use (in kbytes)\n");
  167.   fprintf(stderr, "  -verbose  or  -debug   Emit debug output\n");
  168.   fprintf(stderr, "Switches for wizards:\n");
  169. #ifdef C_ARITH_CODING_SUPPORTED
  170.   fprintf(stderr, "  -arithmetic    Use arithmetic coding\n");
  171. #endif
  172. #ifdef C_MULTISCAN_FILES_SUPPORTED
  173.   fprintf(stderr, "  -nointerleave  Create noninterleaved JPEG file\n");
  174. #endif
  175.   fprintf(stderr, "  -qtables file  Use quantization tables given in file\n");
  176.   fprintf(stderr, "  -sample HxV[,...]  Set JPEG sampling factors\n");
  177.   exit(EXIT_FAILURE);
  178. }
  179.  
  180.  
  181. LOCAL boolean
  182. keymatch (char * arg, const char * keyword, int minchars)
  183. /* Case-insensitive matching of (possibly abbreviated) keyword switches. */
  184. /* keyword is the constant keyword (must be lower case already), */
  185. /* minchars is length of minimum legal abbreviation. */
  186. {
  187.   register int ca, ck;
  188.   register int nmatched = 0;
  189.  
  190.   while ((ca = *arg++) != '\0') {
  191.     if ((ck = *keyword++) == '\0')
  192.       return FALSE;        /* arg longer than keyword, no good */
  193.     if (isupper(ca))        /* force arg to lcase (assume ck is already) */
  194.       ca = tolower(ca);
  195.     if (ca != ck)
  196.       return FALSE;        /* no good */
  197.     nmatched++;            /* count matched characters */
  198.   }
  199.   /* reached end of argument; fail if it's too short for unique abbrev */
  200.   if (nmatched < minchars)
  201.     return FALSE;
  202.   return TRUE;            /* A-OK */
  203. }
  204.  
  205.  
  206. LOCAL int
  207. qt_getc (FILE * file)
  208. /* Read next char, skipping over any comments (# to end of line) */
  209. /* A comment/newline sequence is returned as a newline */
  210. {
  211.   register int ch;
  212.   
  213.   ch = getc(file);
  214.   if (ch == '#') {
  215.     do {
  216.       ch = getc(file);
  217.     } while (ch != '\n' && ch != EOF);
  218.   }
  219.   return ch;
  220. }
  221.  
  222.  
  223. LOCAL long
  224. read_qt_integer (FILE * file)
  225. /* Read an unsigned decimal integer from a quantization-table file */
  226. /* Swallows one trailing character after the integer */
  227. {
  228.   register int ch;
  229.   register long val;
  230.   
  231.   /* Skip any leading whitespace, detect EOF */
  232.   do {
  233.     ch = qt_getc(file);
  234.     if (ch == EOF)
  235.       return EOF;
  236.   } while (isspace(ch));
  237.   
  238.   if (! isdigit(ch)) {
  239.     fprintf(stderr, "%s: bogus data in quantization file\n", progname);
  240.     exit(EXIT_FAILURE);
  241.   }
  242.  
  243.   val = ch - '0';
  244.   while (ch = qt_getc(file), isdigit(ch)) {
  245.     val *= 10;
  246.     val += ch - '0';
  247.   }
  248.   return val;
  249. }
  250.  
  251.  
  252. LOCAL void
  253. read_quant_tables (compress_info_ptr cinfo, char * filename, int scale_factor)
  254. /* Read a set of quantization tables from the specified file.
  255.  * The file is plain ASCII text: decimal numbers with whitespace between.
  256.  * Comments preceded by '#' may be included in the file.
  257.  * There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values.
  258.  * The tables are implicitly numbered 0,1,etc.
  259.  */
  260. {
  261.   /* ZIG[i] is the zigzag-order position of the i'th element of a DCT block */
  262.   /* read in natural order (left to right, top to bottom). */
  263.   static const short ZIG[DCTSIZE2] = {
  264.      0,  1,  5,  6, 14, 15, 27, 28,
  265.      2,  4,  7, 13, 16, 26, 29, 42,
  266.      3,  8, 12, 17, 25, 30, 41, 43,
  267.      9, 11, 18, 24, 31, 40, 44, 53,
  268.     10, 19, 23, 32, 39, 45, 52, 54,
  269.     20, 22, 33, 38, 46, 51, 55, 60,
  270.     21, 34, 37, 47, 50, 56, 59, 61,
  271.     35, 36, 48, 49, 57, 58, 62, 63
  272.     };
  273.   FILE * fp;
  274.   int tblno, i;
  275.   long val;
  276.   QUANT_TBL table;
  277.  
  278.   if ((fp = fopen(filename, "r")) == NULL) {
  279.     fprintf(stderr, "%s: can't open %s\n", progname, filename);
  280.     exit(EXIT_FAILURE);
  281.   }
  282.   tblno = 0;
  283.  
  284.   while ((val = read_qt_integer(fp)) != EOF) { /* read 1st element of table */
  285.     if (tblno >= NUM_QUANT_TBLS) {
  286.       fprintf(stderr, "%s: too many tables in file %s\n", progname, filename);
  287.       exit(EXIT_FAILURE);
  288.     }
  289.     table[0] = (QUANT_VAL) val;
  290.     for (i = 1; i < DCTSIZE2; i++) {
  291.       if ((val = read_qt_integer(fp)) == EOF) {
  292.     fprintf(stderr, "%s: incomplete table in file %s\n", progname, filename);
  293.     exit(EXIT_FAILURE);
  294.       }
  295.       table[ZIG[i]] = (QUANT_VAL) val;
  296.     }
  297.     j_add_quant_table(cinfo, tblno, table, scale_factor, FALSE);
  298.     tblno++;
  299.   }
  300.  
  301.   fclose(fp);
  302. }
  303.  
  304.  
  305. LOCAL void
  306. set_sample_factors (compress_info_ptr cinfo, char *arg)
  307. /* Process a sample-factors parameter string, of the form */
  308. /*     HxV[,HxV,...]    */
  309. {
  310. #define MAX_COMPONENTS 4    /* # of comp_info slots made by jcdeflts.c */
  311.   int ci, val1, val2;
  312.   char ch1, ch2;
  313.  
  314.   for (ci = 0; ci < MAX_COMPONENTS; ci++) {
  315.     if (*arg) {
  316.       ch2 = ',';        /* if not set by sscanf, will be ',' */
  317.       if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3)
  318.     usage();
  319.       if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',')
  320.     usage();        /* syntax check */
  321.       if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) {
  322.     fprintf(stderr, "JPEG sampling factors must be 1..4\n");
  323.     exit(EXIT_FAILURE);
  324.       }
  325.       cinfo->comp_info[ci].h_samp_factor = val1;
  326.       cinfo->comp_info[ci].v_samp_factor = val2;
  327.       while (*arg && *arg++ != ',') /* advance to next segment of arg string */
  328.     ;
  329.     } else {
  330.       /* reached end of parameter, set remaining components to 1x1 sampling */
  331.       cinfo->comp_info[ci].h_samp_factor = 1;
  332.       cinfo->comp_info[ci].v_samp_factor = 1;
  333.     }
  334.   }
  335. }
  336.  
  337.  
  338. LOCAL int
  339. parse_switches (compress_info_ptr cinfo, int last_file_arg_seen,
  340.         int argc, char **argv)
  341. /* Initialize cinfo with default switch settings, then parse option switches.
  342.  * Returns argv[] index of first file-name argument (== argc if none).
  343.  * Any file names with indexes <= last_file_arg_seen are ignored;
  344.  * they have presumably been processed in a previous iteration.
  345.  * (Pass 0 for last_file_arg_seen on the first or only iteration.)
  346.  */
  347. {
  348.   int argn;
  349.   char * arg;
  350.   char * qtablefile = NULL;    /* saves -qtables filename if any */
  351.   int q_scale_factor = 100;    /* default to no scaling for -qtables */
  352.  
  353.   /* (Re-)initialize the system-dependent error and memory managers. */
  354.   jselerror(cinfo->emethods);    /* error/trace message routines */
  355.   jselmemmgr(cinfo->emethods);    /* memory allocation routines */
  356.   cinfo->methods->c_ui_method_selection = c_ui_method_selection;
  357.  
  358.   /* Now OK to enable signal catcher. */
  359. #ifdef NEED_SIGNAL_CATCHER
  360.   emethods = cinfo->emethods;
  361. #endif
  362.  
  363.   /* Set up default JPEG parameters. */
  364.   /* Note that default -quality level here need not, and does not,
  365.    * match the default scaling for an explicit -qtables argument.
  366.    */
  367.   j_c_defaults(cinfo, 75, FALSE); /* default quality level = 75 */
  368.  
  369.   /* Scan command line options, adjust parameters */
  370.  
  371.   for (argn = 1; argn < argc; argn++) {
  372.     arg = argv[argn];
  373.     if (*arg != '-') {
  374.       /* Not a switch, must be a file name argument */
  375.       if (argn <= last_file_arg_seen)
  376.     continue;        /* ignore it if previously processed */
  377.       break;            /* else done parsing switches */
  378.     }
  379.     arg++;            /* advance past switch marker character */
  380.  
  381.     if (keymatch(arg, "arithmetic", 1)) {
  382.       /* Use arithmetic coding. */
  383. #ifdef C_ARITH_CODING_SUPPORTED
  384.       cinfo->arith_code = TRUE;
  385. #else
  386.       fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
  387.           progname);
  388.       exit(EXIT_FAILURE);
  389. #endif
  390.  
  391.     } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
  392.       /* Enable debug printouts. */
  393.       /* On first -d, print version identification */
  394.       if (last_file_arg_seen == 0 && cinfo->emethods->trace_level == 0)
  395.     fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
  396.         JVERSION, JCOPYRIGHT);
  397.       cinfo->emethods->trace_level++;
  398.  
  399.     } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
  400.       /* Force a monochrome JPEG file to be generated. */
  401.       j_monochrome_default(cinfo);
  402.  
  403.     } else if (keymatch(arg, "maxmemory", 1)) {
  404.       /* Maximum memory in Kb (or Mb with 'm'). */
  405.       long lval;
  406.       char ch = 'x';
  407.  
  408.       if (++argn >= argc)    /* advance to next argument */
  409.     usage();
  410.       if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
  411.     usage();
  412.       if (ch == 'm' || ch == 'M')
  413.     lval *= 1000L;
  414.       cinfo->emethods->max_memory_to_use = lval * 1000L;
  415.  
  416.     } else if (keymatch(arg, "nointerleave", 3)) {
  417.       /* Create noninterleaved file. */
  418. #ifdef C_MULTISCAN_FILES_SUPPORTED
  419.       cinfo->interleave = FALSE;
  420. #else
  421.       fprintf(stderr, "%s: sorry, multiple-scan support was not compiled\n",
  422.           progname);
  423.       exit(EXIT_FAILURE);
  424. #endif
  425.  
  426.     } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
  427.       /* Enable entropy parm optimization. */
  428. #ifdef ENTROPY_OPT_SUPPORTED
  429.       cinfo->optimize_coding = TRUE;
  430. #else
  431.       fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
  432.           progname);
  433.       exit(EXIT_FAILURE);
  434. #endif
  435.  
  436.     } else if (keymatch(arg, "quality", 1)) {
  437.       /* Quality factor (quantization table scaling factor). */
  438.       int val;
  439.  
  440.       if (++argn >= argc)    /* advance to next argument */
  441.     usage();
  442.       if (sscanf(argv[argn], "%d", &val) != 1)
  443.     usage();
  444.       /* Set quantization tables (will be overridden if -qtables also given).
  445.        * Note: we make force_baseline FALSE.
  446.        * This means non-baseline JPEG files can be created with low Q values.
  447.        * To ensure only baseline files are generated, pass TRUE instead.
  448.        */
  449.       j_set_quality(cinfo, val, FALSE);
  450.       /* Change scale factor in case -qtables is present. */
  451.       q_scale_factor = j_quality_scaling(val);
  452.  
  453.     } else if (keymatch(arg, "qtables", 2)) {
  454.       /* Quantization tables fetched from file. */
  455.       if (++argn >= argc)    /* advance to next argument */
  456.     usage();
  457.       qtablefile = argv[argn];
  458.       /* we postpone actually reading the file in case -quality comes later */
  459.  
  460.     } else if (keymatch(arg, "restart", 1)) {
  461.       /* Restart interval in MCU rows (or in MCUs with 'b'). */
  462.       long lval;
  463.       char ch = 'x';
  464.  
  465.       if (++argn >= argc)    /* advance to next argument */
  466.     usage();
  467.       if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
  468.     usage();
  469.       if (lval < 0 || lval > 65535L)
  470.     usage();
  471.       if (ch == 'b' || ch == 'B')
  472.     cinfo->restart_interval = (UINT16) lval;
  473.       else
  474.     cinfo->restart_in_rows = (int) lval;
  475.  
  476.     } else if (keymatch(arg, "sample", 2)) {
  477.       /* Set sampling factors. */
  478.       if (++argn >= argc)    /* advance to next argument */
  479.     usage();
  480.       set_sample_factors(cinfo, argv[argn]);
  481.  
  482.     } else if (keymatch(arg, "smooth", 2)) {
  483.       /* Set input smoothing factor. */
  484.       int val;
  485.  
  486.       if (++argn >= argc)    /* advance to next argument */
  487.     usage();
  488.       if (sscanf(argv[argn], "%d", &val) != 1)
  489.     usage();
  490.       if (val < 0 || val > 100)
  491.     usage();
  492.       cinfo->smoothing_factor = val;
  493.  
  494.     } else {
  495.       usage();            /* bogus switch */
  496.     }
  497.   }
  498.  
  499.   /* Post-switch-scanning cleanup */
  500.  
  501.   if (qtablefile != NULL)    /* process -qtables if it was present */
  502.     read_quant_tables(cinfo, qtablefile, q_scale_factor);
  503.  
  504.   return argn;            /* return index of next arg (file name) */
  505. }
  506.  
  507.  
  508. /*
  509.  * The main program.
  510.  */
  511.  
  512. GLOBAL int
  513. main (int argc, char **argv)
  514. {
  515.   struct Compress_info_struct cinfo;
  516.   struct Compress_methods_struct c_methods;
  517.   struct External_methods_struct e_methods;
  518.   int file_index;
  519.  
  520.   /* On Mac, fetch a command line. */
  521. #ifdef THINK_C
  522.   argc = ccommand(&argv);
  523. #endif
  524.  
  525.   progname = argv[0];
  526.  
  527.   /* Set up links to method structures. */
  528.   cinfo.methods = &c_methods;
  529.   cinfo.emethods = &e_methods;
  530.  
  531.   /* Install, but don't yet enable signal catcher. */
  532. #ifdef NEED_SIGNAL_CATCHER
  533.   emethods = NULL;
  534.   signal(SIGINT, signal_catcher);
  535. #ifdef SIGTERM            /* not all systems have SIGTERM */
  536.   signal(SIGTERM, signal_catcher);
  537. #endif
  538. #endif
  539.  
  540.   /* Scan command line: set up compression parameters, input & output files. */
  541.  
  542.   file_index = parse_switches(&cinfo, 0, argc, argv);
  543.  
  544. #ifdef TWO_FILE_COMMANDLINE
  545.  
  546.   if (file_index != argc-2) {
  547.     fprintf(stderr, "%s: must name one input and one output file\n", progname);
  548.     usage();
  549.   }
  550.  
  551.   cinfo.input_file = (FILE *) argv[file_index];
  552.  
  553.   if ((cinfo.output_file = fopen(argv[file_index+1], WRITE_BINARY)) == NULL) {
  554.     fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index+1]);
  555.     exit(EXIT_FAILURE);
  556.   }
  557.  
  558. #else /* not TWO_FILE_COMMANDLINE -- use Unix style */
  559.  
  560.   cinfo.input_file = stdin;    /* default input file */
  561.   cinfo.output_file = stdout;    /* always the output file */
  562.  
  563. #ifdef USE_SETMODE        /* need to hack file mode? */
  564.   setmode(fileno(stdin), O_BINARY);
  565.   setmode(fileno(stdout), O_BINARY);
  566. #endif
  567.  
  568.   if (file_index < argc-1) {
  569.     fprintf(stderr, "%s: only one input file\n", progname);
  570.     usage();
  571.   }
  572.   if (file_index < argc) {
  573.     if ((cinfo.input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
  574.       fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
  575.       exit(EXIT_FAILURE);
  576.     }
  577.   }
  578.  
  579. #endif /* TWO_FILE_COMMANDLINE */
  580.  
  581.   /* Figure out the input file format, and set up to read it. */
  582.   /* select_file_type(&cinfo); */
  583.   jselmultipic(&cinfo);
  584.  
  585. #ifdef PROGRESS_REPORT
  586.   /* Start up progress display, unless trace output is on */
  587.   if (e_methods.trace_level == 0)
  588.     c_methods.progress_monitor = progress_monitor;
  589. #endif
  590.  
  591.   /* Do it to it! */
  592.   jpeg_compress(&cinfo);
  593.  
  594. #ifdef PROGRESS_REPORT
  595.   /* Clear away progress display */
  596.   if (e_methods.trace_level == 0) {
  597.     fprintf(stderr, "\r                \r");
  598.     fflush(stderr);
  599.   }
  600. #endif
  601.  
  602.   /* All done. */
  603.   exit(EXIT_SUCCESS);
  604.   return 0;            /* suppress no-return-value warnings */
  605. }
  606.